#include <iostream>
#include <fstream>
#include <string>
#include "CAuctionMgr.h"
#include "pb_cfg_auction.pb.h"
#include "../cmdinner/CCmdAuctionPayBack.h"
#include "../item/CDropItem.h"
#include "../mainctrl.h"

int CAuctionMgr::LoadConfig(const char* szCfgPath)
{
    int iRet = 0;

    if (szCfgPath == NULL)
    {
        CT_ERROR(("auction Cfg Path is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_auction stAuctionCfg;
    std::fstream stFileInput(szCfgPath, std::ios::in | std::ios::binary);
    if (!stAuctionCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse auction config!"));
        return RET_SYSTEM_FAIL;
    }

    for (int i = 0; i < stAuctionCfg.auction_config_rows_size(); ++i)
    {
        const pb_cfg_auction_pb_cfg_auction_config_unit& stPBUnit = stAuctionCfg.auction_config_rows(i);

        CAuctionConfigUnit stDataConfig;
        stDataConfig._usGoodsId = stPBUnit.goods_id();
        stDataConfig._ucZoneOpenDay = stPBUnit.zone_open_days();

        unsigned char ucAuctionType = stPBUnit.auction_type();
        iRet = _stAuctionCfg.AddAuctionConfig(ucAuctionType, stDataConfig);
        if (iRet)
        {
            CT_ERROR(("%d, %d, %d", iRet, ucAuctionType, stDataConfig._usGoodsId));
            return iRet;
        }
    }

    for (int i = 0; i < stAuctionCfg.auction_item_rows_size(); ++i)
    {
        const pb_cfg_auction_pb_cfg_auction_item_unit& stPBUnit = stAuctionCfg.auction_item_rows(i);

        CAuctionGoodsUnit  stAuctionItem;
        stAuctionItem._usGoodsId = stPBUnit.goods_id();
        stAuctionItem._ucItemType = stPBUnit.item_type();
        stAuctionItem._usItemConfigID = stPBUnit.item_id();
        stAuctionItem._shItemCount = stPBUnit.item_num();
        stAuctionItem._iGoldPrice = stPBUnit.money_gold();
        stAuctionItem._iSilverPrice = stPBUnit.money_silver ();

        if (ITEM_TYPE_CRYSTAL == stAuctionItem._ucItemType)
        {
            CCrystalConfigData stConfigData;
            iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetCrystalConfig(stAuctionItem._usItemConfigID, stConfigData);
        }
        else if (ITEM_TYPE_CARD2 == stAuctionItem._ucItemType)
        {
            CCardConfigData stConfigData;
            iRet = CMainCtrl::m_pstMain->m_stCardMgr._stCardConfig.GetConfig(stAuctionItem._usItemConfigID, stConfigData);
        }
        else if (ITEM_TYPE_MATERIAL== stAuctionItem._ucItemType)
        {
            CMaterialConfigData stConfigData;
            iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetMaterialConfig(stAuctionItem._usItemConfigID, stConfigData);
        }
        else if (ITEM_TYPE_GIFT == stAuctionItem._ucItemType)
        {
            CGiftConfigUnit stConfigData;
            iRet = CMainCtrl::m_pstMain->m_stItemMgr.GetGiftConfig(stAuctionItem._usItemConfigID, stConfigData);
        }
        else
        {
            iRet = ERROR_AUCTION_GOODS_ID;
        }

        if (iRet || stAuctionItem._iGoldPrice < AUCTION_GOLD_PRICE_UNIT || stAuctionItem._iSilverPrice < AUCTION_SILVER_PRICE_UNIT)
        {
            CT_ERROR(("%d, %d, %d, %d", iRet, stAuctionItem._usGoodsId, stAuctionItem._iGoldPrice, stAuctionItem._iSilverPrice));
            return iRet;
        }

        iRet = _stAuctionCfg.AddAuctionGoodsConfig(stAuctionItem);
        if (iRet)
        {
            CT_ERROR(("%d, %d", iRet, stAuctionItem._usGoodsId));
            return iRet;
        }
    }

    return 0;
}

int CAuctionMgr::GetGoodsConfig (unsigned short usGoodId, CAuctionGoodsUnit & stCfg)
{
    if (!CAuctionConfig::IsValidGoods(usGoodId))
    {
        CT_ERROR(("%d", usGoodId));
        return ERROR_AUCTION_GOODS_ID;
    }

    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(usGoodId);
    if (!stGoods.HasConfig())
    {
        CT_ERROR(("%d", usGoodId));
        return ERROR_AUCTION_GOODS_ID;
    }

    stCfg = stGoods;
    return RET_OK;
}

int CAuctionMgr::InitData (CAuctionCommonData & stZoneAuction)
{
    _iLastAuctionEndTime = stZoneAuction._iLastResultTime;
    _iAuctionBeginTime = GetBeginTimeInCfg();
    _iAuctionEndTime = GetBeginEndInCfg();

    UpdateMarNotifyTime(CMainCtrl::m_pstMain->m_iNow);

    if (_iAuctionBeginTime >= _iAuctionEndTime)
    {
        CT_ERROR (("%d,%d", _iAuctionBeginTime, _iAuctionEndTime));
        return ERROR_ACT_ERROR_CFG;
    }

    _bCanOpenBlind = true;
    if (IsAuctionOpen (CMainCtrl::m_pstMain->m_iNow) && stZoneAuction._iLastRefreshTime > 0)
    {
        _bCanOpenBlind = false;  //服务器异常重启后,暗拍数据无法恢复,需要关闭暗拍功能
        _stBlindData.Clear(true);
        CT_WARNING(("%d, %d", CMainCtrl::m_pstMain->m_iNow, stZoneAuction._iLastRefreshTime));
    }    

    //每天0点的时候,更新数据
    InitAuction (stZoneAuction, CMainCtrl::m_pstMain->m_iNow);

    //检查是否每场竞拍都发货了. (a.处理开服时间落在拍卖会开启时间内,  b.还有未结算的拍卖)
    CheckAndTriggerResult (stZoneAuction,  CMainCtrl::m_pstMain->m_iNow);

    return 0;
}

int CAuctionMgr::InitAuction (CAuctionCommonData& stZoneAuction, int iNowTime)
{
    //每天凌晨的时候,更新数据
    if (CTTimeUtils::IsSameDay(stZoneAuction._iLastRefreshTime, iNowTime, 0))
    {
        return 0;
    }

    CT_TRACE(("InitAuction %d, %d", iNowTime, stZoneAuction._iLastRefreshTime));

    // 1.) 检查是否有未结算的
    CheckAndTriggerResult(stZoneAuction, iNowTime);

    // 2.) 清空拍卖纪录和跑马灯信息
    stZoneAuction._stRollMsg.Clear();
    _stMarMsg.Clear();

    // 3.) 换入昨日的拍卖结果
    stZoneAuction.SwapHistory ();    

    // 4.) 生成今日的新物品
    int iRet = RET_OK;
    CAuctionRecord stRecord;
    CAuctionGoodsUnit stGoods;

    //一次生成所有轮次要拍卖的物品,简化处理流程
    int iBeginTime = _iAuctionBeginTime + CTTimeUtils::GetDayBeginSec(iNowTime);
    for( int i = 0; i < MAX_AUCTION_PUBLIC_ROUNDS;  ++i )
    {
        int iRound = i+1;

        EN_AUCTION_TYPE enType = AUCTION_TYPE_PUBLIC;
        if (IsInFinal(iRound))
        {
            enType = AUCTION_TYPE_FINAL;
        }

        //确保拍卖生成不一样的物品
        do
        {
            iRet = _stAuctionCfg.GenerateAuctionGoods(enType, stGoods);
            if (iRet)
            {
                CT_ERROR (("%d, %d", iRet, enType));
                return iRet;
            }

        } while (stZoneAuction._stTodayHis.HasSameGoods(AUCTION_TYPE_PUBLIC, stGoods._usGoodsId));

        stRecord.Clear();
        stRecord._usGoodId = stGoods._usGoodsId;
        stRecord._iSilver = stGoods._iSilverPrice;
        stRecord._iGold = stGoods._iGoldPrice;
        stRecord._uiData = iBeginTime + iRound * AUCTION_SECONS_PER_ROUND;   //预期的结算时间

        CT_TRACE(("%d, %d, %d", iRound, stRecord._usGoodId, stRecord._uiData));

        stZoneAuction._stTodayHis.AddRecord(AUCTION_TYPE_PUBLIC, stRecord);
    }

    //生成暗拍的物品
    iRet = _stAuctionCfg.GenerateAuctionGoods(AUCTION_TYPE_BLIND, stGoods);
    if (iRet)
    {
        CT_ERROR (("%d, %d", iRet, stGoods._usGoodsId));
        return iRet;
    }

    stRecord.Clear();
    stRecord._usGoodId = stGoods._usGoodsId;
    stRecord._iSilver = AUCTION_SILVER_PRICE_UNIT;   //暗拍所有物品的起价都是一样的
    stRecord._iGold = AUCTION_GOLD_PRICE_UNIT;
    stRecord._uiData = iBeginTime + MAX_AUCTION_PUBLIC_ROUNDS * AUCTION_SECONS_PER_ROUND;
    stZoneAuction._stTodayHis.AddRecord(AUCTION_TYPE_BLIND, stRecord);

    //清空暗拍数据
    _stBlindData.Clear(true);
    _bCanOpenBlind = true;

    // 5.) 数据入库
    stZoneAuction._iLastRefreshTime = iNowTime;
    UpdateZoneAuction();

    return 0;
}


//每秒刷新活动状态
int CAuctionMgr::TimeTick (int iNowTime)
{
    if (!CMainCtrl::m_pstMain->m_stZoneOnlineData.HasInited ())
    {
        return 0;
    }

    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;

    //每天0点的时候,更新拍卖物品
    InitAuction (stZoneAuction, iNowTime);

    //触发拍卖结算
    if (iNowTime - _iLastAuctionEndTime >= AUCTION_SECONS_PER_ROUND)
    {
        CheckAndTriggerResult (stZoneAuction,  CMainCtrl::m_pstMain->m_iNow);
    }

    //检查和发送竞拍开始\结束的跑马灯
    CheackAndSendMar (stZoneAuction, iNowTime);

    return RET_OK;
}


int CAuctionMgr::DoReq(MsgReqAuction &stReq, MsgAnsAuction & stAns)
{
    unsigned int uiGid = stReq.gid();
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(uiGid);
    if (iIndex < 0)
    {
        CT_ERROR(("%d", uiGid));
        return RET_NO_USER;
    }
    CPlayerBaseInfo& stPlayerBaseInfo = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex];

    int iOpt = stReq.opt();
    int iRet = 0;

    switch( iOpt )
    {
    case AUCTION_REQ_BLIND:
        iRet = this->BlindAuction(stPlayerBaseInfo, stReq, stAns);
        if (RET_OK == iRet)
        {
            CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(uiGid, NOTIFY_USER_MONEY);
        }
        break;

    case AUCTION_REQ_PUBLIC:
        iRet = this->PublicAuction(stPlayerBaseInfo, stReq, stAns);
        if (RET_OK == iRet)
        {
            CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(uiGid, NOTIFY_USER_MONEY);
        }
        break;

    case AUCTION_REQ_RECORD:
        {
            NotifyBidInfo (uiGid);
        }
        break;

    case AUCTION_REQ_PUBLIC_INFO:
    case AUCTION_REQ_BLIND_INFO:
        {
            GetAuctionInfo(stPlayerBaseInfo._stUserAuctionData, iOpt, stAns);
        }
        break;

    case AUCTION_REQ_TODAY_HIS:
    case AUCTION_REQ_YESDAY_HIS:
        {
            GetAuctionHistory(uiGid, iOpt, stAns);
        }
        break;

    case AUCTION_REQ_MAR:
        {
            NotifyMarInfo(uiGid);
        }
        break;

    default:
        return ERROR_AUCTION_OPT_NONE;
    }

    return iRet;
}


int CAuctionMgr::CheckBackMoneyOnLogin (CPlayerBaseInfo & stPlayerBaseInfo)
{
    CAuctionUserData & stAuctionUser = stPlayerBaseInfo._stUserAuctionData;
    if (0 != stAuctionUser._iBlindGold || 0 != stAuctionUser._iBlindSilver)
    {
        bool bInToday = CTTimeUtils::IsSameDay(stAuctionUser._iBlindTime, CMainCtrl::m_pstMain->m_iNow, AUCTION_RESET_TIME);
        bool IsActOpen = IsAuctionOpen(CMainCtrl::m_pstMain->m_iNow);
        if ((false == bInToday) || (true == bInToday && false == IsActOpen) || (false == _bCanOpenBlind))
        {
            // 暗拍的数据未入库, 服务器异常时, 只能在用户登录时判断退款
            // 1.)用户参加了非今天的暗拍。  2) 用户参加了今天的拍卖,且拍卖活动已经结束了
            PayBackOneUserBlindMoney (stPlayerBaseInfo, CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData._stTodayHis._stBlind);
        }
    }

    return 0;
}


//高价竞拍
int CAuctionMgr::PublicAuction (CPlayerBaseInfo& stPlayerBaseInfo, MsgReqAuction & stReq, MsgAnsAuction & stAns)
{
    int iNowTime = CMainCtrl::m_pstMain->m_iNow;

    int iRound = GetAuctionRound (iNowTime);
    if (!CAuctionHistory::IsValidRound(AUCTION_TYPE_PUBLIC, iRound))
    {
        return ERROR_AUCTION_EXPIRE_TIME;
    }

    if (iRound != stReq.round())
    {
        return ERROR_AUCTION_EXPIRE_TIME;
    }

    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;
    CAuctionRecord & stRecord = stZoneAuction._stTodayHis.GetRecord(AUCTION_TYPE_PUBLIC, iRound);

    int iRet = 0;
    int iMoney = stReq.money();
    int iMoneyType = stReq.money_type();

    if (IsInFinal(iRound) && (AUCTION_MONEY_TYPE_GOLD != iMoneyType))  //压轴竞拍只支持金币
    {
        return ERROR_AUCTION_MONEY_TYPE;
    }

    iRet = PreCheckPublic (stPlayerBaseInfo, stRecord, iMoneyType, iMoney);
    CHECK_RETURN(iRet);

    //扣当前用户的款
    CAuctionRecord stOldRecord = stRecord;
    iRet = DeductMoney (stPlayerBaseInfo, stRecord, iMoneyType, iMoney);
    if (iRet)
    {
        CT_ERROR(("%d, %d", stPlayerBaseInfo._uiGID));
        return iRet;
    }

    //保存出价记录
    CAuctionRecord  stBidRecord;
    stBidRecord._iTime = iNowTime;
    stBidRecord._usGoodId = stRecord._usGoodId;
    if (AUCTION_MONEY_TYPE_GOLD == iMoneyType)
    {
        stBidRecord._uiGoldGID = stPlayerBaseInfo._uiGID;
        stBidRecord._iGold = iMoney;
    }
    else
    {
        stBidRecord._uiSilverGID = stPlayerBaseInfo._uiGID;
        stBidRecord._iSilver = iMoney;
    }

    //最后五分钟,每笔出价都要触发跑马灯
    if (GetRoundEndTime(iNowTime) < MAX_AUCTION_MAR_TIME)
    {
        AddMarRecord (AUCTION_PUBLIC_LIVE, iNowTime, stBidRecord);

        SendZoneMar(AUCTION_PUBLIC_LIVE, stBidRecord);
    }

    //出价记录
    stBidRecord._uiData = (IsInFinal(iRound) ? AUCTION_TYPE_FINAL : AUCTION_TYPE_PUBLIC);
    //跟前台有特殊约定，MsgAuctionRecord的gold_gid表示当前出价最高的人. silver_gid表示被超过的人
    stBidRecord._uiGoldGID = stPlayerBaseInfo._uiGID;  
    stBidRecord._uiSilverGID = (AUCTION_MONEY_TYPE_GOLD == iMoneyType ? stOldRecord._uiGoldGID : stOldRecord._uiSilverGID);
    stBidRecord._iSilver = (AUCTION_MONEY_TYPE_SILVER == iMoneyType ? iMoney : 0);
    AddBidRecord (stZoneAuction, stBidRecord);

    //数据入库
    UpdateUserAuction(stPlayerBaseInfo);
    UpdateZoneAuction();

    //竞价信息发生变化
    iRet = NotifyChangeInfo (AUCTION_TYPE_PUBLIC);
    if (iRet)
    {
        CT_WARNING(("%d, %d", iRet, iRound));
    }

    //返还上个竞价用户的金钱, 发送信封提示
    iRet = PayBackPublicMoney (stOldRecord, iMoneyType, stPlayerBaseInfo._uiGID);
    if (iRet)
    {
        CT_ERROR(("%d, %d", stPlayerBaseInfo._uiGID));
        return iRet;
    }

    CT_TRACE(("PublicAuction: %d, %d, %d", stPlayerBaseInfo._uiGID, iMoneyType, iMoney));

    return RET_OK;
}

//暗拍竞价
int CAuctionMgr::BlindAuction (CPlayerBaseInfo & stPlayerBaseInfo,  MsgReqAuction & stReq, MsgAnsAuction & stAns)
{
    if (!IsAuctionOpen(CMainCtrl::m_pstMain->m_iNow))   //活动未开启直接报错
    {
        stAns.set_ret(ERROR_AUCTION_EXPIRE_TIME);
        return 0;
    }
    
    if (!_bCanOpenBlind)
    {
        stAns.set_ret(ERROR_AUCTION_CLOSE_BLIND);
        return 0;
    }

    int iMoney = stReq.money();
    unsigned char ucMoneyType = stReq.money_type();

    int iRet = 0;
    iRet = PreCheckBlind (stPlayerBaseInfo, ucMoneyType, iMoney);
    CHECK_RETURN(iRet);

    unsigned int uiGID = stPlayerBaseInfo._uiGID;
    int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(uiGID);
    if (iIndex < 0)
    {
        CT_ERROR(("online user %u has no online data", uiGID));
        return ERROR_NO_ONLINE_DATA;
    }
    CPlayerOnlineData& stPlayerOnlineData = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex];

    iRet = DeductBlindMoney (stPlayerBaseInfo, ucMoneyType, iMoney);
    if (iRet)
    {
        CT_ERROR(("%d, %d"));
        return iRet;
    }

    iRet = _stBlindData.AddBlindBid (ucMoneyType, iMoney, stPlayerBaseInfo._uiGID);
    if (iRet)
    {
        CT_ERROR(("%d, %d"));
        return iRet;
    }

    //保存出价记录
    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;
    CAuctionRecord & stBlind = stZoneAuction._stTodayHis.GetRecord(AUCTION_TYPE_BLIND, 0);

    CAuctionRecord  stBidRecord;
    stBidRecord._iTime = CMainCtrl::m_pstMain->m_iNow;
    stBidRecord._uiData = AUCTION_TYPE_BLIND;
    stBidRecord._usGoodId = stBlind._usGoodId;
    if (ucMoneyType == AUCTION_MONEY_TYPE_GOLD)
    {
        stBidRecord._uiGoldGID = stPlayerBaseInfo._uiGID;
        stBidRecord._iGold = iMoney;
    }
    else
    {
        stBidRecord._uiSilverGID = stPlayerBaseInfo._uiGID;
        stBidRecord._iSilver = iMoney;
    }
    AddBidRecord (stZoneAuction, stBidRecord);

    //数据入库
    UpdateUserAuction(stPlayerBaseInfo);
    UpdateZoneAuction();

    stPlayerOnlineData._stUserAuction = stPlayerBaseInfo._stUserAuctionData;

    //通知前台出价变化
    iRet = NotifyChangeInfo (AUCTION_TYPE_BLIND);
    if (iRet)
    {
        CT_WARNING(("%d", iRet));
    }

    CT_TRACE(("BlindAuction: %d, %d, %d", uiGID, ucMoneyType, iMoney));

    return iRet;
}

//返还金钱给竞价用户
int CAuctionMgr::PayBackPublicMoney (CAuctionRecord & stRecord, int iMoneyType, unsigned int uiNewGid)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;

    unsigned uiGid = (AUCTION_MONEY_TYPE_SILVER == iMoneyType) ? stRecord._uiSilverGID : stRecord._uiGoldGID;
    if (0 == uiGid)
    {
        return 0;
    }

    CDropItem stDropItem;
    CDropItemData stDropItemData;

    stDropItem.SetOssModule(OSS_MODULE_AUCTION);

    int iMoney = (AUCTION_MONEY_TYPE_SILVER == iMoneyType) ? stRecord._iSilver : stRecord._iGold;
    if (AUCTION_MONEY_TYPE_SILVER == iMoneyType)
    {
        stDropItemData._ucItemType = ITEM_TYPE_SILVER;
    }
    else
    {
        stDropItemData._ucItemType = ITEM_TYPE_GOLD;
    }

    stDropItemData._usItemConfigID = 0;
    stDropItemData._iItemCount = iMoney;
    stDropItem.Drop (stDropItemData);

    pstMain->m_stItemMgr.DropItem(NULL, uiGid, stDropItem, false);

    //发给信标tips给出价用户
    CTips stTips;
    stTips._iType = 18;
    stTips._iData1 = uiNewGid;     //新的竞价最高用户
    stTips._iData2 = iMoneyType;
    stTips._iData3 = iMoney;

    pstMain->SendTips(uiGid, stTips);
    return 0;
}


int CAuctionMgr::GetAuctionRound (int iNowTime)
{    
    int iTodayBeginTime = CTTimeUtils::GetDayBeginSec(iNowTime) + _iAuctionBeginTime;
    if (iNowTime < iTodayBeginTime)
    {
        return 0;
    }

    return CT_MAX(((iNowTime - iTodayBeginTime) / AUCTION_SECONS_PER_ROUND + 1), 0);
}

int CAuctionMgr::GetRoundEndTime (int iNowTime)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    if (!IsAuctionOpen(iNowTime))
    {
        return 0;
    }

    int iBeginTime = pstMain->m_stActMgr.GetBeginTime( ACT_ID_AUCTION );
    int iOffSetTime = iNowTime - iBeginTime;
    if (iOffSetTime >= 0)
    {
        return (AUCTION_SECONS_PER_ROUND - (iOffSetTime % AUCTION_SECONS_PER_ROUND));
    }
    else
    {
        CT_ERROR(("%d, %d", iNowTime, iBeginTime));
    }

    return 0;
}

bool CAuctionMgr::IsInFinal (int iRound)
{
    return (MAX_AUCTION_PUBLIC_ROUNDS == iRound || 0 == iRound);
}


//获取活动信息
int CAuctionMgr::GetAuctionInfo(CAuctionUserData & stUserAuction, int iOpt, MsgAnsAuction & stAns)
{    
    int iNowTime = CMainCtrl::m_pstMain->m_iNow;

    if (!IsAuctionOpen(iNowTime))   //活动未开启直接报错
    {
        stAns.set_ret(ERROR_AUCTION_EXPIRE_TIME);
        return 0;
    }

    switch (iOpt)
    {
        case AUCTION_REQ_PUBLIC_INFO:
            {
                GetPublicGoodsInfo (iNowTime, stAns);
            }
            break;

        case AUCTION_REQ_BLIND_INFO:
            {   
                if (_bCanOpenBlind)
                {
                    GetBlindGoodsInfo (stUserAuction, stAns);
                }
                else
                {
                    stAns.set_ret (ERROR_AUCTION_CLOSE_BLIND);
                    return 0;
                }
            }
            break;

        default:
            return ERROR_AUCTION_OPT_NONE;
    }

    return RET_OK;
}


int CAuctionMgr::GetAuctionRecord (EN_AUCTION_TYPE enType, int iRound, CAuctionRecord & stRecord)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    CAuctionCommonData & stCommonData = pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;

    if (!stCommonData._stTodayHis.IsValidRound(enType, iRound))
    {
        return ERROR_AUCTION_ROUND;
    }

    stRecord = stCommonData._stTodayHis.GetRecord(enType, iRound);
    return 0;
}

int CAuctionMgr::GetAuctionGoodsInfo (CAuctionRecord & stRecord, unsigned char ucMoneType, MsgBidItem & stBidItem)
{
    unsigned int uiGid = 0;
    int iMoney = 0;
    if (AUCTION_MONEY_TYPE_SILVER == ucMoneType)
    {
        uiGid = stRecord._uiSilverGID;
        iMoney = stRecord._iSilver;
    }
    else
    {
        uiGid = stRecord._uiGoldGID;
        iMoney = stRecord._iGold;
    }

    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    stBidItem.set_type(ucMoneType);
    stBidItem.set_highest_money(iMoney);
    stBidItem.set_gid(uiGid);
    stBidItem.set_name(pstMain->m_stRoleMgr.GetRoleName(uiGid));

    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);
    MsgGridItemInfo * pstItem = stBidItem.mutable_item ();
    pstItem->set_item_type(stGoods._ucItemType);
    pstItem->set_item_config_id(stGoods._usItemConfigID);
    pstItem->set_item_count(stGoods._shItemCount);
    pstItem->set_invalid_time(CMainCtrl::m_pstMain->m_iNow + GetRoundEndTime(pstMain->m_iNow));

    return 0;
}

int CAuctionMgr::GetBlindGoodsInfo (CAuctionUserData & stUserData, unsigned char ucMoneType, MsgBidItem & stBidItem)
{
    int iMyOffer = 0;
    if (AUCTION_MONEY_TYPE_SILVER == ucMoneType)
    {
        iMyOffer = stUserData._iBlindSilver;
    }
    else
    {
        iMyOffer = stUserData._iBlindGold;
    }

    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    CAuctionRecord & stRecord = pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData._stTodayHis.GetRecord(AUCTION_TYPE_BLIND,0);
    stBidItem.set_type(ucMoneType);
    stBidItem.set_bidder_cnt(_stBlindData.GetBidCount(ucMoneType));
    stBidItem.set_my_offer(iMyOffer);

    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);
    MsgGridItemInfo * pstItem = stBidItem.mutable_item ();
    pstItem->set_item_type(stGoods._ucItemType);
    pstItem->set_item_config_id(stGoods._usItemConfigID);
    pstItem->set_item_count(stGoods._shItemCount);
    pstItem->set_invalid_time(pstMain->m_stActMgr.GetEndTime(ACT_ID_AUCTION));

    return 0;
}

int CAuctionMgr::GetAuctionRecordInfo (CAuctionRecord & stRecord, EN_AUCTION_TYPE enType, MsgAuctionRecord & stMsgRecord)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;

    if (AUCTION_TYPE_FINAL == enType)
    {
        if (stRecord.HasRoundResult() && (0 != stRecord._uiGoldGID))  //设置压轴拍卖王
        {
            int iIndex = pstMain->m_stClanMgr.GetClanIndex(stRecord._uiGoldGID);
            if (iIndex >= 0)
            {
                CClanEntry & stClan = pstMain->m_stClanMgr.GetClanEntry(iIndex);
                stMsgRecord.set_clan_id(stClan._uiClanId);
                stMsgRecord.set_clan_name(stClan._szName());
            }
        }
    }
    else
    {
        stMsgRecord.set_silver_gid(stRecord._uiSilverGID);
        stMsgRecord.set_silver_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiSilverGID));
        stMsgRecord.set_silver(stRecord._iSilver);
    }

    stMsgRecord.set_type(enType);
    stMsgRecord.set_gold_gid(stRecord._uiGoldGID);
    stMsgRecord.set_gold_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));
    stMsgRecord.set_gold(stRecord._iGold);

    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);
    MsgGridItemInfo * pstItem = stMsgRecord.mutable_item ();
    pstItem->set_item_type(stGoods._ucItemType);
    pstItem->set_item_config_id(stGoods._usItemConfigID);
    pstItem->set_item_count(stGoods._shItemCount);
    pstItem->set_invalid_time(stRecord._iTime);   //时间为0,表示拍卖正在进行中

    return 0;
}

//触发暗拍结算
int CAuctionMgr::TriggerBlindResult(CAuctionCommonData & stAuctionData, int iNowTime)
{
    CAuctionRecord & stRecord = stAuctionData._stTodayHis.GetRecord(AUCTION_TYPE_BLIND, 0);
    if (stRecord.HasRoundResult())
    {
        CT_ERROR (("%d, %d", stRecord._iTime, stRecord._uiData));
        return 0;
    }

    CT_TRACE(("TriggerBlindResult: %d", iNowTime));

    int iIndex = _stBlindData._hPrice2Gid.GetHeadIndex();
    while (iIndex >= 0)
    {
        CAucBidKey stKey = _stBlindData._hPrice2Gid.GetKeyByIndex(iIndex);
        unsigned int uiGid = _stBlindData._hPrice2Gid[iIndex];

        iIndex = _stBlindData._hPrice2Gid.GetNextIndex(iIndex);

        if (0 == uiGid)
        {
            continue;
        }

        if (AUCTION_MONEY_TYPE_SILVER == stKey._ucMoneyType)
        {
            if ((0 == stRecord._uiSilverGID) || (stKey._iMoney < stRecord._iSilver))
            {
                stRecord._uiSilverGID = uiGid;
                stRecord._iSilver = stKey._iMoney;
            }
        }
        else
        {
            if ((0 == stRecord._uiGoldGID) || (stKey._iMoney < stRecord._iGold))
            {
                stRecord._uiGoldGID = uiGid;
                stRecord._iGold = stKey._iMoney;
            }
        }

        //触发暗卖成功者的结算
        _stBlindData.AddBackMoneyUser(uiGid);       
    }

    //清除今天的数据
    _stBlindData.Clear(false);   

    //返还暗拍失败用户金钱, 已经去除了暗拍成功的用户.
    SendGoods(AUCTION_TYPE_BLIND, stRecord);

    //数据入库
    _iLastAuctionEndTime = stRecord.EndTime();
    stRecord._iTime = iNowTime;
    stAuctionData._iLastResultTime = iNowTime;
    UpdateZoneAuction();

    //发送跑马灯信息
    AddMarRecord (AUCTION_TYPE_BLIND, iNowTime, stRecord);

    //退款
    TriggerPayBackBlindMoney ();

    //发送全服跑马灯
    SendZoneMar (AUCTION_TYPE_BLIND, stRecord);

    return 0;
}

//触发竞拍结算
int CAuctionMgr::TriggerPublicResult (CAuctionRecord & stRecord, int iNowTime)
{
    if (stRecord.HasRoundResult())   //已经结算了
    {
        CT_ERROR (("%d, %d", stRecord._iTime, stRecord._uiData));
        return 0;
    }

    CT_TRACE(("TriggerPublicResult: %d", iNowTime));

    //发货
    SendGoods(AUCTION_TYPE_PUBLIC, stRecord);

    //更新纪录
    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;
    _iLastAuctionEndTime = stRecord.EndTime();
    stRecord._iTime = iNowTime;
    stZoneAuction._iLastResultTime = iNowTime;
    UpdateZoneAuction();

    //发送跑马灯信息
    AddMarRecord (AUCTION_TYPE_PUBLIC, iNowTime, stRecord);

    NotifyChangeInfo (AUCTION_TYPE_PUBLIC);

    //发送全服跑马灯
    SendZoneMar (AUCTION_TYPE_PUBLIC, stRecord);

    return 0;
}

//触发压轴结算
int CAuctionMgr::TriggerFinalResult(CAuctionCommonData & stAuctionData,  int iNowTime)
{
    CAuctionRecord & stRecord = stAuctionData._stTodayHis.GetFinalRecord();
    if (stRecord.HasRoundResult())   //已经结算了
    {
        CT_ERROR (("%d, %d", stRecord._iTime, stRecord._uiData));
        return 0;
    }

    CT_TRACE(("TriggerFinalResult: %d", iNowTime));

    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    int iRet = 0;

    //设置拍卖王    
    stAuctionData._uiKingGid = stRecord._uiGoldGID;
    if (0 != stAuctionData._uiKingGid)
    {
        unsigned int uiGid = stAuctionData._uiKingGid;
        SendGoods(AUCTION_TYPE_FINAL, stRecord);

        //增加称号
        //int iTitleExpiredTime = CTTimeUtils::GetDayBeginSec(iNowTime) + AUCTION_SECONS_PER_ROUND * (MAX_AUCTION_PUBLIC_ROUNDS - 1) + 86400;
        int iTitleExpiredTime = iNowTime + 86400;
        pstMain->m_stRoleMgr.DropTitle(uiGid, ROLE_TITLE_AUCTION, iTitleExpiredTime);

        //增加家族战斗银币增益
        iRet = pstMain->m_stClanMgr.SetAuctionBuff(uiGid,  iTitleExpiredTime);
        if (iRet)
        {
            CT_ERROR(("%d, %d", iRet, uiGid));
        }
    }

    //数据入库
    _iLastAuctionEndTime = stRecord.EndTime();
    stRecord._iTime = iNowTime;
    stAuctionData._iLastResultTime = iNowTime;
    UpdateZoneAuction();

    AddMarRecord(AUCTION_TYPE_FINAL, iNowTime, stRecord);    

    //发送全服跑马灯
    SendZoneMar (AUCTION_TYPE_FINAL, stRecord);

    return 0;
}

void CAuctionMgr::SendGoods(EN_AUCTION_TYPE enType, CAuctionRecord & stRecord)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    int iRet = RET_OK;

    CTips stTips;
    stTips._iType =  (AUCTION_TYPE_BLIND == enType ? 24 : 23);  //发送竞拍成功tips;
    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);
    stTips._iData1 = stGoods._ucItemType;
    stTips._iData2 = stGoods._usItemConfigID;
    stTips._iData3 = stGoods._shItemCount;

    CDropItemData stDropItemData;
    stDropItemData._ucItemType = ITEM_TYPE_GIFT;
    stDropItemData._usItemConfigID = ACT_BONUS_TYPE_AUCTION;
    stDropItemData._iItemCount = 1;  
    stDropItemData._iData1 = stRecord._usGoodId;  //在CCmdDropItem中有特殊处理
    
    CDropItem stDropItem;
    stDropItem.SetOssModule(OSS_MODULE_AUCTION);
    stDropItem.Drop(stDropItemData);
    
    if (0 != stRecord._uiSilverGID)
    {
        iRet = pstMain->m_stItemMgr.DropItem(0, stRecord._uiSilverGID, stDropItem, false);
        if (RET_OK == iRet)
        {
            pstMain->SendTips(stRecord._uiSilverGID, stTips);
        }
        else
        {
            CT_ERROR (("%d, %d", iRet, stRecord._uiSilverGID, stRecord._usGoodId));
        }
    }

    if (0 != stRecord._uiGoldGID)
    {
        //拍卖成功后的消费返利.
        stDropItemData.Clear();
        stDropItemData._ucItemType = ITEM_TYPE_USE_GOLD_POINT;
        stDropItemData._iItemCount = stRecord._iGold;            
        stDropItem.Drop(stDropItemData);

        iRet = pstMain->m_stItemMgr.DropItem(0, stRecord._uiGoldGID, stDropItem, false);
        if (RET_OK == iRet)
        {
            pstMain->SendTips(stRecord._uiGoldGID, stTips);
        }
        else
        {
            CT_ERROR (("%d, %d", iRet, stRecord._uiGoldGID, stRecord._usGoodId));
        }
    }

}

int CAuctionMgr::PreCheckPublic (CPlayerBaseInfo & stPlayerBaseInfo, CAuctionRecord & stRecord, int iMoneyType, int iMoney)
{
    //检查活动金钱类型
    if (iMoney <= 0)
    {
        return ERROR_AUCTION_MONEY_FMT;
    }

    unsigned int  uiGid = stPlayerBaseInfo._uiGID;
    if (AUCTION_MONEY_TYPE_GOLD == iMoneyType)
    {
        if (stRecord._uiGoldGID == uiGid)
        {
            return ERROR_HAS_JOIN_AUCTION;
        }

        if (stPlayerBaseInfo._iGold < iMoney)
        {
            return ERROR_GOLD_LESS;
        }

        if (0 != (iMoney % AUCTION_GOLD_PRICE_UNIT))
        {
            return ERROR_AUCTION_MONEY_FMT;
        }

        if ((iMoney < stRecord._iGold)  //可以等于起拍价
            || (0 != stRecord._uiGoldGID  && iMoney == stRecord._iGold))
        {
            return ERROR_AUCTION_PRICE_TOO_LOW;
        }
    }
    else if (AUCTION_MONEY_TYPE_SILVER == iMoneyType)
    {
        if (stRecord._uiSilverGID == uiGid)
        {
            return ERROR_HAS_JOIN_AUCTION;
        }

        if (stPlayerBaseInfo._i64Silver < iMoney)
        {
            return ERROR_SILVER_LESS;
        }

        if (0 != (iMoney % AUCTION_SILVER_PRICE_UNIT))
        {
            return ERROR_AUCTION_MONEY_FMT;
        }

        if ((iMoney < stRecord._iSilver)
            || (0 != stRecord._uiSilverGID && iMoney == stRecord._iSilver))
        {
            return ERROR_AUCTION_PRICE_TOO_LOW;
        }
    }
    else
    {
        return ERROR_AUCTION_MONEY_TYPE;
    }

    return 0;
}

int CAuctionMgr::PreCheckBlind (CPlayerBaseInfo & stPlayerBaseInfo, int iMoneyType, int iMoney)
{
    //检查用户是否已经参与过此活动
    CAuctionUserData & stUserAuction = stPlayerBaseInfo._stUserAuctionData;

    if (iMoney <= 0)
    {
        return ERROR_AUCTION_MONEY_FMT;
    }

    if (AUCTION_MONEY_TYPE_GOLD == iMoneyType)
    {
        if (stUserAuction._iBlindGold > 0)
        {
            return ERROR_HAS_JOIN_AUCTION;
        }

        if (0 != (iMoney % AUCTION_GOLD_PRICE_UNIT))
        {
            return ERROR_AUCTION_MONEY_FMT;
        }

        if (stPlayerBaseInfo._iGold < iMoney)
        {
            return ERROR_GOLD_LESS;
        }
    }
    else if (AUCTION_MONEY_TYPE_SILVER == iMoneyType)
    {
        if (stUserAuction._iBlindSilver > 0)
        {
            return ERROR_HAS_JOIN_AUCTION;
        }

        if (0 != (iMoney % AUCTION_SILVER_PRICE_UNIT))
        {
            return ERROR_AUCTION_MONEY_FMT;
        }

        if (stPlayerBaseInfo._i64Silver < iMoney)
        {
            return ERROR_SILVER_LESS;
        }
    }
    else
    {
        return ERROR_AUCTION_MONEY_TYPE;
    }

    return 0;
}

//扣钱
int CAuctionMgr::DeductMoney (CPlayerBaseInfo & stPlayerBaseInfo, CAuctionRecord & stRecord, int iMoneyType, int iMoney)
{
    int iRet = RET_OK;
    if (AUCTION_MONEY_TYPE_GOLD == iMoneyType)
    {
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_28, iMoney);
        CHECK_RETURN(iRet);

        stRecord._uiGoldGID = stPlayerBaseInfo._uiGID;
        stRecord._iGold = iMoney;

    }
    else
    {
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, iMoney, OSS_MONEY_MODULE_28);
        CHECK_RETURN(iRet);

        stRecord._uiSilverGID = stPlayerBaseInfo._uiGID;
        stRecord._iSilver = iMoney;
    }

    return iRet;
}


int CAuctionMgr::DeductBlindMoney (CPlayerBaseInfo & stPlayerBaseInfo, int iMoneyType, int iMoney)
{
    int iRet = RET_OK;
    CAuctionUserData & stUserAuction = stPlayerBaseInfo._stUserAuctionData;
    if (AUCTION_MONEY_TYPE_GOLD == iMoneyType)
    {
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_41, iMoney);
        CHECK_RETURN(iRet);

        stUserAuction._iBlindGold = iMoney;
    }
    else
    {
        iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, iMoney, OSS_MONEY_MODULE_41);
        CHECK_RETURN(iRet);

        stUserAuction._iBlindSilver = iMoney;
    }

    stUserAuction._iBlindTime = CMainCtrl::m_pstMain->m_iNow;

    return RET_OK;
}

int CAuctionMgr::GetAuctionHistory (unsigned int uiGid, int iOpt, MsgAnsAuction & stAns)
{
    if ((AUCTION_REQ_TODAY_HIS != iOpt)
        && (AUCTION_REQ_YESDAY_HIS != iOpt))
    {
        return ERROR_AUCTION_OPT_NONE;
    }

    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;
    CAuctionHistory & stHistory = (AUCTION_REQ_TODAY_HIS == iOpt ? stZoneAuction._stTodayHis : stZoneAuction._stYestodayHis);

    int iMaxRound = MAX_AUCTION_PUBLIC_ROUNDS;
    if (AUCTION_REQ_TODAY_HIS == iOpt)
    {
        if (!IsAuctionOpen(CMainCtrl::m_pstMain->m_iNow) )
        {
            CAuctionRecord & stRecrod = stHistory.GetFinalRecord();
            if (!stRecrod.HasRoundResult())  //今天还未开始过拍卖
            {
                return 0;
            }
        }
        else
        {
            iMaxRound = GetAuctionRound(CMainCtrl::m_pstMain->m_iNow);
        }
    }

    if (!CAuctionHistory::IsValidRound(AUCTION_TYPE_PUBLIC, iMaxRound))
    {
        CT_ERROR(("%d, %d", iMaxRound, CMainCtrl::m_pstMain->m_iNow));
        return ERROR_AUCTION_ROUND;
    }

    for (int iRound = 1; iRound <= iMaxRound; iRound++)
    {
        if (!IsInFinal(iRound))
        {
            CAuctionRecord & stRecod = stHistory.GetRecord(AUCTION_TYPE_PUBLIC, iRound);
            if (!stRecod.HasRoundResult())
            {
                continue;
            }

            MsgAuctionRecord * pstRecord = stAns.add_history();
            GetAuctionRecordInfo(stRecod, AUCTION_TYPE_PUBLIC, *pstRecord);
            pstRecord->mutable_item()->set_valid_time(stRecod._uiData - AUCTION_SECONS_PER_ROUND);
            pstRecord->mutable_item()->set_invalid_time(stRecod._uiData);
        }
        else
        {
            CAuctionRecord & stRecod = stHistory.GetFinalRecord();
            if (!stRecod.HasRoundResult())
            {
                continue;
            }

            MsgAuctionRecord * pstRecord = stAns.add_history();
            GetAuctionRecordInfo(stRecod, AUCTION_TYPE_FINAL, *pstRecord);
            pstRecord->mutable_item()->set_valid_time(stRecod._uiData - AUCTION_SECONS_PER_ROUND);
            pstRecord->mutable_item()->set_invalid_time(stRecod._uiData);

            pstRecord = stAns.add_history();
            CAuctionRecord & stBlind = stHistory.GetRecord(AUCTION_TYPE_BLIND, 0);  //暗拍
            if (!stBlind.HasRoundResult())
            {
                continue;
            }

            GetAuctionRecordInfo(stBlind, AUCTION_TYPE_BLIND, *pstRecord);
            pstRecord->mutable_item()->set_valid_time(stBlind._uiData - AUCTION_SECONS_PER_ROUND*MAX_AUCTION_PUBLIC_ROUNDS);
            pstRecord->mutable_item()->set_invalid_time(stBlind._uiData);
        }
    }

    return RET_OK;
}


int CAuctionMgr::GetAuctionItem (CAuctionUserData & stUserAuctionData, CDropItem & stBonusItem)
{
    if (stUserAuctionData._astPending.Size() <= 0)
    {
        return ERROR_AUCTION_GOODS_NONE;
    }

    unsigned short usGoodId = stUserAuctionData._astPending[0];
    stUserAuctionData._astPending.DelOneItem(0);

    if (!CAuctionConfig::IsValidGoods(usGoodId))
    {
        CT_ERROR(("%d", usGoodId));
        return ERROR_AUCTION_GOODS_ID;
    }

    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(usGoodId);
    if (!stGoods.HasConfig())
    {
        CT_ERROR(("%d", usGoodId));
        return ERROR_AUCTION_GOODS_ID;
    }

    CDropItemData stData;
    stData._ucItemType = stGoods._ucItemType;
    stData._usItemConfigID = stGoods._usItemConfigID;
    stData._iItemCount = stGoods._shItemCount;

    stBonusItem.Drop(stData);
    return 0;
}

int CAuctionMgr::GetAuctionItemSpace (CAuctionUserData & stUserAuctionData)
{
    return 1;
}


int CAuctionMgr::TriggerPayBackBlindMoney ()
{
    CCmdAuctionPayBack* pstCmd = (CCmdAuctionPayBack *) CT_CMDFACTORY->CreateCmd(ID_MAIN_INNER_AUCTION_PAYBACK);
    if (!pstCmd)
    {
        CT_WARNING(("factory create cmd(%d) failed.",ID_MAIN_INNER_AUCTION_PAYBACK));
        return RET_SYSTEM_FAIL;
    }

    pstCmd->pstMainCtrl = CMainCtrl::m_pstMain;    

    return pstCmd->Do(NULL);
}


int CAuctionMgr::PayBackOneUserBlindMoney (CPlayerBaseInfo & stPlayerBaseInfo, CAuctionRecord & stBlind)
{
    unsigned int uiGid = stPlayerBaseInfo._uiGID;
    CAuctionUserData & stAuctionUser = stPlayerBaseInfo._stUserAuctionData;

    CDropItem stDropItem;
    CDropItemData stDropItemData;

    stDropItem.SetOssModule(OSS_MODULE_AUCTION);

    CTips stTips;
    stTips._iType = 19;

    if (stAuctionUser._iBlindSilver > 0 && uiGid != stBlind._uiSilverGID)  //竞拍成功的不要退款
    {
        stDropItemData._ucItemType = ITEM_TYPE_SILVER;
        stDropItemData._iItemCount = stAuctionUser._iBlindSilver;
        stDropItem.Drop(stDropItemData);

        stTips._iData1 = AUCTION_MONEY_TYPE_SILVER;
        stTips._iData2 = stAuctionUser._iBlindSilver;  
        CMainCtrl::m_pstMain->SendTips(uiGid, stTips);

        CT_TRACE(("%d, %d", uiGid, stDropItemData._iItemCount));
    }

    if (stAuctionUser._iBlindGold > 0 && uiGid != stBlind._uiGoldGID)
    {
        stDropItemData._ucItemType = ITEM_TYPE_GOLD;
        stDropItemData._iItemCount = stAuctionUser._iBlindGold;
        stDropItem.Drop(stDropItemData);

        stTips._iData1 = AUCTION_MONEY_TYPE_GOLD;
        stTips._iData2 = stAuctionUser._iBlindGold;
        CMainCtrl::m_pstMain->SendTips(uiGid, stTips);

        CT_TRACE(("%d, %d", uiGid, stDropItemData._iItemCount));
    }

    stAuctionUser.Clear();

    CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL, uiGid, stDropItem, false);
    return 0;
}

int CAuctionMgr::GetPublicGoodsInfo (int iNowTime,  MsgAnsAuction & stAns)
{
    CAuctionRecord stRecord;
    int iRound = GetAuctionRound (iNowTime);
    int iRet = GetAuctionRecord (AUCTION_TYPE_PUBLIC, iRound, stRecord);
    if (iRet)
    {
        stAns.set_ret(iRet);
        return 0;
    }

    if (stRecord.HasRoundResult())
    {
        stAns.set_ret(ERROR_AUCTION_EXPIRE_TIME);
        return 0;
    }

    MsgAuctionInfo * pstInfo = stAns.mutable_info();
    pstInfo->set_round(iRound);
    if (IsInFinal(iRound))
    {
        pstInfo->set_type(AUCTION_TYPE_FINAL);
    }
    else
    {
        pstInfo->set_type(AUCTION_TYPE_PUBLIC);
        GetAuctionGoodsInfo (stRecord, AUCTION_MONEY_TYPE_SILVER, *(pstInfo->add_items()));
    }

    GetAuctionGoodsInfo (stRecord, AUCTION_MONEY_TYPE_GOLD, *(pstInfo->add_items()));
    return 0;
}

int CAuctionMgr::GetBlindGoodsInfo (CAuctionUserData & stUserAuction,  MsgAnsAuction & stAns)
{
    MsgAuctionInfo * pstInfo = stAns.mutable_info();

    pstInfo->set_type(AUCTION_TYPE_BLIND);
    GetBlindGoodsInfo (stUserAuction, AUCTION_MONEY_TYPE_GOLD, *(pstInfo->add_items()));
    GetBlindGoodsInfo (stUserAuction, AUCTION_MONEY_TYPE_SILVER, *(pstInfo->add_items()));
    return 0;
}


void CAuctionMgr::AddMarRecord (EN_AUCTION_TYPE enType, int iNowTime, CAuctionRecord & stNowRecord)
{
    if (_stMarMsg.Size() >= MAX_AUCTION_MAR_MSG)
    {
        _stMarMsg.ShiftDelOneItem(0);
    }

    //每一轮的结算时,清除竞价信息
    if (enType != AUCTION_PUBLIC_LIVE)
    {
        for (int i = 0; i < _stMarMsg.Size(); )
        {
            if (AUCTION_PUBLIC_LIVE == _stMarMsg[i]._uiData)
            {
                _stMarMsg.DelOneItem(i);
            }
            else
            {
                ++i;
            }
        }
    }

    //发送场景的跑马灯信息
    CAuctionRecord  stMarRecord;
    stMarRecord._iTime = stNowRecord._uiData;  //结算时间
    stMarRecord._usGoodId = stNowRecord._usGoodId;
    stMarRecord._uiData = enType;

    bool bNeedNotify = false;
    if (0 != stNowRecord._uiSilverGID)
    {
        stMarRecord._uiSilverGID = stNowRecord._uiSilverGID;
        stMarRecord._iSilver = stNowRecord._iSilver;
        _stMarMsg.AddOneItem (stMarRecord);
        bNeedNotify = true;
    }

    if (0 != stNowRecord._uiGoldGID)
    {
        stMarRecord._uiSilverGID = 0;
        stMarRecord._iSilver = 0;

        stMarRecord._uiGoldGID = stNowRecord._uiGoldGID;
        stMarRecord._iGold = stNowRecord._iGold;

        _stMarMsg.AddOneItem (stMarRecord);
        bNeedNotify = true;
    }

    //暗拍没结果的时候. (本期没有出价唯一的幸运者，真遗憾！)
    if (AUCTION_TYPE_BLIND == enType && 0 == stNowRecord._uiSilverGID && 0 == stNowRecord._uiGoldGID)
    {
        _stMarMsg.AddOneItem(stMarRecord);
        bNeedNotify = true; 
    }

    if (bNeedNotify)
    {
        NotifyMarInfo (0);
    }
}

void CAuctionMgr::AddBidRecord (CAuctionCommonData & stZoneAuction, CAuctionRecord & stBidHis)
{
    if (stZoneAuction._stRollMsg.Size() >= MAX_AUCTION_ROLL_MSG)
    {
        stZoneAuction._stRollMsg.ShiftDelOneItem(0);
    }

    stZoneAuction._stRollMsg.AddOneItem(stBidHis);

    NotifyBidInfo (0);
}

void CAuctionMgr::NotifyBidInfo (unsigned int uiGid)
{
    MsgAnsAuction stAns;

    CAuctionCommonData & stZoneAuction = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData._stAuctionZoneData;
    for (int i = 0 ; i < stZoneAuction._stRollMsg.Size(); i++)
    {
        MsgAuctionRecord * pstHis = stAns.add_history();
        CAuctionRecord & stBidHis = stZoneAuction._stRollMsg[i];

        GetBidRecordInfo (stBidHis, (EN_AUCTION_TYPE)stBidHis._uiData, *pstHis);
    }

    NotifyAuctionMapUsers(uiGid, AUCTION_REQ_RECORD, stAns);

    return ;
}

void CAuctionMgr::NotifyMarInfo (unsigned int uiGid)
{
    MsgAnsAuction stAns;
    for (int i = 0 ; i < _stMarMsg.Size(); i++)
    {
        MsgAuctionRecord * pstHis = stAns.add_marquee();
        CAuctionRecord & stBidHis = _stMarMsg[i];

        EN_AUCTION_TYPE enType = (EN_AUCTION_TYPE)stBidHis._uiData;
        if (AUCTION_TYPE_PUBLIC == enType)
        {
            pstHis->set_round(GetAuctionRound(stBidHis._iTime - 1));  //根据结算时间来推算,有可能不准确
        }

        GetAuctionRecordInfo (stBidHis, enType, *pstHis);
    }

    NotifyAuctionMapUsers(uiGid, AUCTION_REQ_MAR, stAns);

    return ;
}


int CAuctionMgr::NotifyChangeInfo (EN_AUCTION_TYPE enType)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    int iRet = RET_OK;

    MsgAnsAuction stAns;

    if (AUCTION_TYPE_BLIND == enType)
    {
        PBMsgHead stMsgHead;
        stMsgHead.set_msgid(ID_MAIN_AUCTION);
        stMsgHead.set_msgret(0);
        stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

        CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY stUserInMap;
        iRet = pstMain->m_stMapViews.GetAllMapUsers(MAP_ID_AUCTION, stUserInMap);
        if (iRet)
        {
            CT_ERROR(("%d", iRet));
            return iRet;
        }

        for (int i = 0; i < stUserInMap.Size(); i++)
        {
            unsigned int uiGid = stUserInMap[i];
            int iIndex = pstMain->m_stPlayerOnlineDataHash.HashFind(uiGid);
            if (iIndex >= 0)
            {
                stAns.Clear();
                stAns.set_opt(AUCTION_REQ_BLIND_INFO);
                iRet = GetBlindGoodsInfo (pstMain->m_stPlayerOnlineDataHash[iIndex]._stUserAuction, stAns);
                if (iRet)
                {
                    continue;
                }

                pstMain->m_stEncodeBuf.Clear();
                pstMain->EncodePBMsg(stMsgHead, pstMain->m_stEncodeBuf);
                pstMain->EncodePBMsg(stAns, pstMain->m_stEncodeBuf);

                pstMain->NotifyOnlineUser (uiGid, pstMain->m_stEncodeBuf);
            }
            else
            {
                CT_WARNING (("%d", uiGid));
            }
        }
    }
    else
    {
        stAns.set_opt(AUCTION_REQ_PUBLIC_INFO);
        iRet = GetPublicGoodsInfo (pstMain->m_iNow, stAns);
        if (iRet)
        {
            CT_ERROR(("%d", iRet));
            return iRet;
        }

        NotifyAuctionMapUsers (0, AUCTION_REQ_PUBLIC_INFO, stAns);
    }

    return 0;
}


void CAuctionMgr::NotifyAuctionMapUsers (unsigned int uiGid, int iOpt, MsgAnsAuction & stAns)
{
    PBMsgHead stMsgHead;
    stMsgHead.set_msgid(ID_MAIN_AUCTION);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    stAns.set_opt(iOpt);

    CMainCtrl * pstMain = CMainCtrl::m_pstMain;
    pstMain->m_stEncodeBuf.Clear();
    pstMain->EncodePBMsg(stMsgHead, pstMain->m_stEncodeBuf);
    pstMain->EncodePBMsg(stAns, pstMain->m_stEncodeBuf);

    if (0 != uiGid)
    {
        pstMain->NotifyOnlineUser (uiGid, pstMain->m_stEncodeBuf);
    }
    else
    {
        CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY stUserInMap;
        int iRet = pstMain->m_stMapViews.GetAllMapUsers(MAP_ID_AUCTION, stUserInMap);
        if (iRet)
        {
            CT_ERROR(("%d", iRet));
            return ;
        }

        for (int i = 0; i < stUserInMap.Size(); i++)
        {
            uiGid = stUserInMap[i];
            if (pstMain->m_stPlayerOnline.CheckOnline(uiGid))
            {
                pstMain->NotifyOnlineUser (uiGid, pstMain->m_stEncodeBuf);
            }
        }
    }
}

int CAuctionMgr::GetBeginTimeInCfg ()
{
    int iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg (ACT_ID_AUCTION);
    if (iIndex < 0)
    {
        CT_ERROR(("%d", iIndex));
        return 0;
    }

    CActCfgData & stActCfgData =  CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);
    return stActCfgData.GetSegBeginTime(1);
}

int CAuctionMgr::GetBeginEndInCfg ()
{
    int iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg (ACT_ID_AUCTION);
    if (iIndex < 0)
    {
        CT_ERROR(("%d", iIndex));
        return 0;
    }

    CActCfgData & stActCfgData =  CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);
    return stActCfgData.GetSegEndTime (1);
}

void CAuctionMgr::CheckAndTriggerResult (CAuctionCommonData & stZoneAuction, int iNowTime)
{
    if (stZoneAuction._iLastRefreshTime <= 0)  //拍卖会系统未初始化
    {
        return ;
    }

    for (int i = 0; i < stZoneAuction._stTodayHis._stPublic.Size(); i++)
    {
        CAuctionRecord & stRecord = stZoneAuction._stTodayHis._stPublic[i];
        if ((!stRecord.HasRoundResult()) && (iNowTime >= stRecord.EndTime()))
        {
            if (IsInFinal(i+1))
            {
                TriggerFinalResult(stZoneAuction, iNowTime);
            }
            else
            {
                TriggerPublicResult(stRecord, iNowTime);
            }
        }
    }

    CAuctionRecord & stBlind = stZoneAuction._stTodayHis._stBlind;
    if ((!stBlind.HasRoundResult()) && (iNowTime >= stBlind.EndTime()))
    {
        TriggerBlindResult(stZoneAuction, iNowTime);
    }
}


void CAuctionMgr::UpdateZoneAuction ()
{
    CZoneData& stZoneData = CMainCtrl::m_pstMain->m_stZoneOnlineData._stZoneData;
    CVarObjectKey stKey;
    stKey.m_chDataType = DT_ZONE_DATA;
    stKey.m_u64ID = stZoneData._uiZoneID;
    CMainCtrl::m_pstMain->UpdateData(stKey, stZoneData, VOP_UPDATE);
}

void CAuctionMgr::UpdateUserAuction (CPlayerBaseInfo & stPlayerBaseInfo)
{
    CVarObjectKey stKey;
    stKey.m_chDataType = DT_PLAYER_BASE_INFO;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    CMainCtrl::m_pstMain->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);
}


int CAuctionMgr::GetBidRecordInfo (CAuctionRecord & stRecord, EN_AUCTION_TYPE enType, MsgAuctionRecord & stMsgRecord)
{
    CMainCtrl * pstMain = CMainCtrl::m_pstMain;

    switch (enType)
    {
    case AUCTION_TYPE_BLIND:
    case AUCTION_TYPE_FINAL:
        {
            if (stRecord._iSilver > 0)
            {
                stMsgRecord.set_silver_gid(stRecord._uiSilverGID);
                stMsgRecord.set_silver_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiSilverGID));
            }
            else
            {
                stMsgRecord.set_gold_gid(stRecord._uiGoldGID);
                stMsgRecord.set_gold_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));                
            }
        }
        break;

    case AUCTION_TYPE_PUBLIC:
        {
            if (stRecord._iSilver > 0)
            {
                stMsgRecord.set_silver_gid(stRecord._uiGoldGID);
                stMsgRecord.set_silver_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));                
            }
            else
            {
                stMsgRecord.set_gold_gid(stRecord._uiGoldGID);
                stMsgRecord.set_gold_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));                
            }

            stMsgRecord.set_former_gid(stRecord._uiSilverGID);
            stMsgRecord.set_former_name(pstMain->m_stRoleMgr.GetRoleName(stRecord._uiSilverGID));
        }
        break;

    default:
        CT_ERROR(("%d", enType));
        return 0;
    }

    stMsgRecord.set_type(enType);    
    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);
    MsgGridItemInfo * pstItem = stMsgRecord.mutable_item ();
    pstItem->set_item_type(stGoods._ucItemType);
    pstItem->set_item_config_id(stGoods._usItemConfigID);
    pstItem->set_item_count(stGoods._shItemCount);
    pstItem->set_invalid_time(stRecord._iTime);

    return 0;
}

bool CAuctionMgr::IsAuctionOpen (int iNowTime)
{
    int iSeconds = CTTimeUtils::GetSecOfDay(iNowTime);
    if (iSeconds >= _iAuctionBeginTime && iSeconds < _iAuctionEndTime)
    {
        return true;
    }

    return false;
}


void CAuctionMgr::SendZoneMar (EN_AUCTION_TYPE enType, const CAuctionRecord & stRecord)
{
    //发送全区的跑马灯信息
    CAuctionGoodsUnit & stGoods = _stAuctionCfg.GetAuctionGoodsConfig(stRecord._usGoodId);

    switch (enType)
    {
    case AUCTION_TYPE_PUBLIC:
        {
            if (stRecord._uiSilverGID != 0)
            {
                MsgTips stTips;
                stTips.set_type(1040);
                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRecord._uiSilverGID));

                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));
                stTips.add_tip_argument(CTStringUtils::IntToString(AUCTION_MONEY_TYPE_SILVER));

                SendAuctionTips(stTips);    
            }

            if (stRecord._uiGoldGID != 0)
            {
                MsgTips stTips;
                stTips.set_type(1040);
                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));                

                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));
                stTips.add_tip_argument(CTStringUtils::IntToString(AUCTION_MONEY_TYPE_GOLD));

                SendAuctionTips(stTips);    
            }
        }
        break;

    case AUCTION_TYPE_BLIND:
        {
            if (0 == stRecord._uiSilverGID && 0 == stRecord._uiGoldGID)
            {
                MsgTips stTips;
                stTips.set_type(1038);
                SendAuctionTips(stTips);  
                return ;
            }           
            
            if (stRecord._uiSilverGID != 0)
            {
                MsgTips stTips;
                stTips.set_type(1039);
                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRecord._uiSilverGID));
                stTips.add_tip_argument(CTStringUtils::IntToString(stRecord._iSilver));
                stTips.add_tip_argument(CTStringUtils::IntToString(AUCTION_MONEY_TYPE_SILVER));
                

                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));                
                
                SendAuctionTips(stTips);    
            }

            if (stRecord._uiGoldGID != 0)
            {
                MsgTips stTips;
                stTips.set_type(1039);
                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));
                stTips.add_tip_argument(CTStringUtils::IntToString(stRecord._iGold));
                stTips.add_tip_argument(CTStringUtils::IntToString(AUCTION_MONEY_TYPE_GOLD));                

                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));

                SendAuctionTips(stTips);    
            }
        }
        break;

    case AUCTION_TYPE_FINAL:
        {
            if (stRecord._uiGoldGID != 0)
            {
                MsgTips stTips;
                stTips.set_type(1042);

                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(stRecord._uiGoldGID));

                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
                stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));                

                stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stClanMgr.GetUserClanName(stRecord._uiGoldGID));

                SendAuctionTips(stTips);    
            }
        }
        break;


    case AUCTION_FINAL_NOTICE:
        {           
            MsgTips stTips;
            stTips.set_type(1041);

            stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
            stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));

            SendAuctionTips(stTips);

        }
        break;

    case AUCTION_PUBLIC_LIVE:
        {
            MsgTips stTips;
            stTips.set_type(1043);

            unsigned char ucMoneyType = (0 == stRecord._uiGoldGID ? AUCTION_MONEY_TYPE_SILVER : AUCTION_MONEY_TYPE_GOLD);
            int iMoney = (0 == stRecord._uiGoldGID ? stRecord._iSilver : stRecord._iGold);
            unsigned int uiGid = (0 != stRecord._uiGoldGID ? stRecord._uiGoldGID : stRecord._uiSilverGID);
            stTips.add_tip_argument(CMainCtrl::m_pstMain->m_stRoleMgr.GetRoleName(uiGid));
            stTips.add_tip_argument(CTStringUtils::IntToString(iMoney));
            stTips.add_tip_argument(CTStringUtils::IntToString(ucMoneyType));
            SendAuctionTips(stTips);
        }
        break;

    case AUCTION_PUBLIC_WILL_END:
        {
            MsgTips stTips;
            stTips.set_type(1061);

            stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._ucItemType));
            stTips.add_tip_argument(CTStringUtils::IntToString(stGoods._usItemConfigID));
            SendAuctionTips(stTips);
        }
        break;

    default:
        CT_ERROR(("%d, %d", enType, stRecord._usGoodId));
    }   
}

void CAuctionMgr::SendAuctionTips (MsgTips& stTips)
{
    PBMsgHead stMsgHead;
    stMsgHead.set_time(CMainCtrl::m_pstMain->m_iNow);
    stMsgHead.set_msgid(ID_MAIN_TIPS);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead, CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stTips, CMainCtrl::m_pstMain->m_stEncodeBuf);

    const CTArray<unsigned int, MAX_PLAYER_ONLINE>& astAllUsers = CMainCtrl::m_pstMain->m_stPlayerOnline.GetAllOnlineUser();

    for (int i = 0; i < astAllUsers.Size(); ++i)
    {
        unsigned int uiGid = astAllUsers[i];
        int iIndex = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash.HashFind(uiGid);
        if (iIndex < 0)
        {
            continue;
        }

         CPlayerOnlineData & stOnlineData = CMainCtrl::m_pstMain->m_stPlayerOnlineDataHash[iIndex];
        if (MAP_ID_AUCTION != stOnlineData._uiNowMapID)
        {
            CMainCtrl::m_pstMain->NotifyOnlineUser(uiGid, CMainCtrl::m_pstMain->m_stEncodeBuf);
        }
    }
}

void CAuctionMgr::UpdateMarNotifyTime (int iNowTime)
{
    _iNeedSendPublicMarTime = CTTimeUtils::GetDayBeginSec(iNowTime) + _iAuctionBeginTime + 3600 - NOTICE_PUBLIC_AUCTION_SECONDS;
    _iNeedSendFinalMarTime = CTTimeUtils::GetDayBeginSec(iNowTime) + _iAuctionEndTime - 3600 - NOTICE_FINAL_AUCTION_SECONDS;

    int iSeonds =  CTTimeUtils::GetSecOfDay(iNowTime);
    if (iSeonds > _iAuctionBeginTime && iSeonds < _iAuctionEndTime)   //今天的拍卖会正在进行中
    {
       _iNeedSendPublicMarTime += ((iSeonds - _iAuctionBeginTime)/AUCTION_SECONS_PER_ROUND * AUCTION_SECONS_PER_ROUND);

       int iEndOffsetTime = (AUCTION_SECONS_PER_ROUND - ((iSeonds - _iAuctionBeginTime) % AUCTION_SECONS_PER_ROUND));   //提前三分钟, 分钟通知一次
       if (iEndOffsetTime <= 60)
       {
           _iNeedSendPublicMarTime += AUCTION_SECONS_PER_ROUND;    //下一轮播
       }

       if (iEndOffsetTime > 60 && iEndOffsetTime < NOTICE_PUBLIC_AUCTION_SECONDS)
       {
           _iNeedSendPublicMarTime += ((NOTICE_PUBLIC_AUCTION_SECONDS/60 - iEndOffsetTime/ 60) * 60);
       }

       //压轴竞拍提前通知
       int iFinalOffsetTime = _iAuctionEndTime - AUCTION_SECONS_PER_ROUND - CTTimeUtils::GetSecOfDay(iNowTime);
       if (iFinalOffsetTime <= 60)
       {
           _iNeedSendFinalMarTime += 86400;  //第二天的通知时间
       }

       if (iFinalOffsetTime > 60 && iFinalOffsetTime < NOTICE_FINAL_AUCTION_SECONDS)
       {
           _iNeedSendFinalMarTime += ((NOTICE_FINAL_AUCTION_SECONDS/60 - iFinalOffsetTime/ 60) * 60);  //提前三分钟开始, 每分钟通知一次
       }
    }
    
    //播完压轴竞拍的提示,时间应该置为第二天的
    if (CTTimeUtils::GetSecOfDay(_iNeedSendPublicMarTime) > _iAuctionEndTime)
    {
        _iNeedSendPublicMarTime = CTTimeUtils::GetDayBeginSec(iNowTime + 86400) + _iAuctionBeginTime + 3600 - NOTICE_PUBLIC_AUCTION_SECONDS;
    }

    if (iSeonds >= _iAuctionEndTime)  //今天的已经结束,通知时间改为明天的
    {
        _iNeedSendPublicMarTime += 86400;
        _iNeedSendFinalMarTime += 86400;   
    }

    CT_TRACE(("UpdateMarNotifyTime %d, %d, %d", iNowTime, _iNeedSendPublicMarTime, _iNeedSendFinalMarTime));
}

void CAuctionMgr::CheackAndSendMar (CAuctionCommonData & stZoneAuction, int iNowTime)
{
    bool bNeedUpdateTime = false;

    //拍卖会竞拍结束前5分钟增加一条跑马灯
    if (iNowTime > _iNeedSendPublicMarTime)
    {
        CAuctionRecord stRecord;
        int iRound = GetAuctionRound (iNowTime);
        int iRet = GetAuctionRecord (AUCTION_TYPE_PUBLIC, iRound, stRecord);
        if (iRet == RET_OK)
        {
            SendZoneMar(AUCTION_PUBLIC_WILL_END, stRecord);
            CMainCtrl::m_pstMain->FlushSendCache();
        }
        
        bNeedUpdateTime = true;        
    }

    //压轴竞拍开始前3分钟,发送全服跑马灯    
    if (iNowTime > _iNeedSendFinalMarTime)
    {
        SendZoneMar(AUCTION_FINAL_NOTICE, stZoneAuction._stTodayHis.GetFinalRecord());
        CMainCtrl::m_pstMain->FlushSendCache();

        bNeedUpdateTime = true;
    }

    if (bNeedUpdateTime)
    {
        UpdateMarNotifyTime (iNowTime);   //更新下次通知时间        
    }
}
